package com.wondertek.poms.sync.manager;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.wondertek.poms.common.constant.Constants;
import com.wondertek.poms.core.config.RedisDistributedLock;
import com.wondertek.poms.core.service.IContentService;
import com.wondertek.poms.core.service.IPrdContService;
import com.wondertek.poms.core.service.IPrdInfoService;
import com.wondertek.poms.core.service.ISyncTaskService;
import com.wondertek.poms.dao.po.Content;
import com.wondertek.poms.dao.po.PrdInfo;
import com.wondertek.poms.dao.po.ProductInfoPackage;
import com.wondertek.poms.dao.po.SyncTask;
import com.wondertek.poms.dao.transVo.TransferMessageVo;
import com.wondertek.poms.sync.manager.main.LiveBillManager;
import com.wondertek.poms.sync.manager.main.MainAssertManager;
import com.wondertek.poms.sync.manager.main.NoProductMainAssertManager;
import com.wondertek.poms.sync.manager.main.NoProductSubSetManager;
import com.wondertek.poms.sync.manager.main.NormalLiveBillManager;
import com.wondertek.poms.sync.manager.main.SpecialLiveBillManager;
import com.wondertek.poms.sync.manager.main.SpecialMainAssertManager;
import com.wondertek.poms.sync.manager.main.SpecialSubSetManager;
import com.wondertek.poms.sync.manager.main.SubSetManager;
import com.wondertek.poms.sync.utils.SourceUtil;

import cn.hutool.crypto.SecureUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * <p><b>StartProcess Description:</b> 同步入包主流程</p>
 * @author douzi
 * <b>DATE</b> 2020年11月12日 下午2:51:13
 */
@Slf4j
@Component
@Data
public class StartProcess {
	@Value("${platform.sign:2}")
	private String platformSign;
    @Autowired
    IPrdContService prdContService;
    @Autowired
    IContentService contentService;
    @Autowired
    LiveBillManager liveBillManager;
    @Autowired
    SubSetManager subSetManager;
    @Autowired
    MainAssertManager mainAssertManager;
    @Autowired
    SpecialLiveBillManager specialLiveBillManager;
    @Autowired
    SpecialSubSetManager specialSubSetManager;
    @Autowired
    SpecialMainAssertManager specialMainAssertManager;
    @Autowired
    NormalLiveBillManager noProductLiveBillManager;
    @Autowired
    NoProductSubSetManager noProductSubSetManager;
    @Autowired
    NoProductMainAssertManager noProductMainAssertManager;
    @Autowired
    private SourceUtil sourceUtil;
    @Autowired
    private RedisDistributedLock lock;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private IPrdInfoService prdInfoService;
    @Autowired
    private ISyncTaskService syncTaskService;
    
    @Async(value = "threadPoolA")
    public void fastProcess(String message) {
    	log.info("内容同步主流程|mq消息：" + message);
    	TransferMessageVo tm = JSON.parseObject(message, TransferMessageVo.class);
        process(tm);
    }

    /**
	 * <p><b>Title:</b> process</p>
	 * <p><b>Description:</b> 主业务流程 </p>
	 * type: 0浏览,1点播，2直播，3下载，4点播+下载，5模拟直播，6内容集，7精简编码，8精简直播，9精简模拟直播，10：剧集 12互联网直播
	 * formtype: 6：剧集（壳）7：剧集的单集8：非剧集9：专辑10：预留（内容集）11：图文单篇12：图文集13：直播节目
	 * @author douzi
	 * @param vo
	 */
    public void process(TransferMessageVo tm) {
    	boolean isSuccess = true;
    	SyncTask st = tm.getSyncTask();
        try {
			List<ProductInfoPackage> pips = tm.getProductInfoPackages();
			if (pips != null && pips.size() > 0) {
				pips.stream().parallel().filter(pip -> platformSign.equals(pip.getType()))
//				pips.stream().filter(pip -> platformSign.equals(pip.getType()))
					.forEach(pip -> {
						log.info("入包主流程|二级产品:" + pip.getProductInfoPackageId() + "|媒资id:" + st.getAssetId() + "|内容id:" + st.getContentId());
						prdInfo(pip, st);
					});
			}
			
			// 开启小屏需要处理的普通包、父子包业务
			if (Constants.SYNC_SMALL.equals(platformSign)) {
				Map<String, List<List<PrdInfo>>> piMaps = prdInfoService.getNotPackagePrdInfo();
				List<PrdInfo> normalList = piMaps.get("normal").get(0);//普通产品包
				List<List<PrdInfo>> special = piMaps.get("special");//V0,V5,V15
				
				log.info("内容普通包主流程|媒资id:" + st.getAssetId() + "|内容id:" + st.getContentId() + "|普通包个数:" + normalList.size());
				if (normalList != null && normalList.size() > 0) {
					normalIn(normalList, st);
				}
				
				log.info("内容父子包主流程|媒资id:" + st.getAssetId() + "|内容id:" + st.getContentId() + "|父子包套数:" + special.size());
				if (special != null && special.size() > 0) {
					specialIn(special, st);
				}
			}
        } catch(Exception e) {
        	isSuccess = false;
        	log.info(st.getContentId() + "内容同步出现问题： ", e);
        } finally {
        	callback(tm.getSyncTask(), isSuccess);
        }
    }

	private void callback(SyncTask st, boolean isSuccess) {
    	log.info("内容同步主流程|业务数据：" + st.getContentId() + "媒资id：" + st.getAccessId() + "同步是否成功：" + isSuccess);
		try {
			// 删除同步锁以及去重key
			if (st.getAssetId() != null) {
				String requestId = redisTemplate.opsForValue().get(Constants.SYNC_LOCK_REQUESTID + st.getAssetId());
				log.info("key:" + Constants.SYNC_LOCK_REQUESTID + st.getAssetId() + "|value:" + requestId + "|contentId:" + st.getContentId());
				if (requestId != null) {
					// 1.解锁
			        boolean result = lock.unLock(Constants.SYNC_LOCK_PREFIX + st.getAssetId(), requestId);
					log.info("redis 释放锁==>" + Constants.SYNC_LOCK_PREFIX + st.getAssetId() + ":" + requestId
							+ " result:" + result + "|contentId:" + st.getContentId());
					// 2.删key
			        String key = st.getContentId() + Constants.REDIS_KEY_SPLIT
			                + st.getOprCode()
			                + Constants.REDIS_KEY_SPLIT
			                + st.getUpdateFields();
			        String md5Key = SecureUtil.md5(key);
			        boolean del = redisTemplate.delete(md5Key);
		            log.info("redis 删除去重key==>" + md5Key + " result:" + del + "|contentId:" + st.getContentId());
					// 3.删本身
		            del = redisTemplate.delete(Constants.SYNC_LOCK_REQUESTID + st.getAssetId());
		            log.info("redis 删除Requestid key==>" + Constants.SYNC_LOCK_REQUESTID + st.getAssetId() + " result:" + del + "|contentId:" + st.getContentId());
				}
			}
		} catch(Exception e) {
			log.error("内容同步主流程|业务数据：" + st.getContentId() + "媒资id：" + st.getAccessId() + "解锁出错:", e);
		} finally {
        	st.setStatus(isSuccess ? 2 : 3);
            syncTaskService.save(st);
            
            sourceUtil.pomsResponse(st, isSuccess);
		}
	}

	/**
     * <p><b>Title:</b> productInfo</p>
     * <p><b>Description:</b> 二级产品入包流程</p>
     * @author douzi
     * @param pip
     * @param syncTask
     */
    public void prdInfo(ProductInfoPackage pip, SyncTask st) {
    	log.info("入包主流程|二级产品:" + pip.getProductInfoPackageId() + "|媒资id:" + st.getAssetId() + "|内容id:" + st.getContentId() + "|需要online:" + pip.getOnline());
    	if (pip.getOnline()) {
    		Content c = contentService.findWholeByContentId(st.getContentId());
    		
    		switch (c.getFormType()) {
				case Constants.ASSET_FORM_TYPE_7:
					if (null != c.getSerialContentId()) {
						subSetManager.subSetProcess(c, st, pip);
					} else {
						log.info("内容同步主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|子集不存在剧集壳id");
//						mainAssertManager.mainProcess(c, st, pip);
					}
					break;
				case Constants.ASSET_FORM_TYPE_13:
					if (null != c.getLiveContentId()) {
						liveBillManager.liveBillProcess(c, st, pip);
					} else {
						log.info("内容同步主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|直播节目没有直播频道id");
					}
					break;
				case Constants.ASSET_FORM_TYPE_6:
				case Constants.ASSET_FORM_TYPE_8:
				case Constants.ASSET_FORM_TYPE_10:
				case Constants.ASSET_FORM_TYPE_11:
				case Constants.ASSET_FORM_TYPE_12:
				case Constants.ASSET_FORM_TYPE_14:
				case Constants.ASSET_FORM_TYPE_15:
				case Constants.ASSET_FORM_TYPE_16:
					mainAssertManager.mainProcess(c, st, pip);
					break;
				default:
					log.info("内容同步主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|不属于任何一种媒资类型:" + c.getFormType());
					break;
			}
    	} else {
    		mainAssertManager.productInfoPackageDelProcess(pip, st);
    	}
    }
    
    /**
     * <p><b>Title:</b> productInfo</p>
     * <p><b>Description:</b> 商品包入包流程</p>
     * @author douzi
     * @param pip
     * @param syncTask
     */
    public void normalIn(List<PrdInfo> normalList, SyncTask st) {
    	Content c = contentService.findWholeByContentId(st.getContentId());
		
		switch (c.getFormType()) {
			case Constants.ASSET_FORM_TYPE_13:
				if (null != c.getLiveContentId()) {
					noProductLiveBillManager.liveBillProcess(c, st, normalList);
				} else {
					log.info("内容普通包主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|直播节目没有直播频道id");
				}
				break;
			case Constants.ASSET_FORM_TYPE_7:
				if (null != c.getSerialContentId()) {
					noProductSubSetManager.subSetProcess(c, st, normalList);
				} else {
					log.info("内容普通包主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|子集不存在剧集壳id");
//						mainAssertManager.mainProcess(c, st, pip);
				}
				break;
			case Constants.ASSET_FORM_TYPE_6:
			case Constants.ASSET_FORM_TYPE_8:
			case Constants.ASSET_FORM_TYPE_10:
			case Constants.ASSET_FORM_TYPE_11:
			case Constants.ASSET_FORM_TYPE_12:
			case Constants.ASSET_FORM_TYPE_14:
			case Constants.ASSET_FORM_TYPE_15:
			case Constants.ASSET_FORM_TYPE_16:
				noProductMainAssertManager.mainProcess(c, st, normalList);
				break;
			default:
				log.info("内容普通包主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|不属于任何一种媒资类型:" + c.getFormType());
				break;
		}
    }
    

    /**
     * <p><b>Title:</b> specialIn</p>
     * <p><b>Description:</b> 父子包业务</p>
     * @author douzi
     * @param special
     * @param st
     */
    private void specialIn(List<List<PrdInfo>> special, SyncTask st) {
    	Content c = contentService.findWholeByContentId(st.getContentId());
		
		switch (c.getFormType()) {
			case Constants.ASSET_FORM_TYPE_13:
				if (null != c.getLiveContentId()) {
					specialLiveBillManager.liveBillProcess(c, st, special);
				} else {
					log.info("内容父子包主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|直播节目没有直播频道id");
				}
				break;
			case Constants.ASSET_FORM_TYPE_7:
				if (null != c.getSerialContentId()) {
					specialSubSetManager.subSetProcess(c, st, special);
				} else {
					log.info("内容父子包主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|子集不存在剧集壳id");
//						mainAssertManager.mainProcess(c, st, pip);
				}
				break;
			case Constants.ASSET_FORM_TYPE_6:
			case Constants.ASSET_FORM_TYPE_8:
			case Constants.ASSET_FORM_TYPE_10:
			case Constants.ASSET_FORM_TYPE_11:
			case Constants.ASSET_FORM_TYPE_12:
			case Constants.ASSET_FORM_TYPE_14:
			case Constants.ASSET_FORM_TYPE_15:
			case Constants.ASSET_FORM_TYPE_16:
				specialMainAssertManager.mainProcess(c, st, special);
				break;
			default:
				log.info("内容父子包主流程|媒资:" + st.getAssetId() + "|内容:" + c.getContentId() + "|不属于任何一种媒资类型:" + c.getFormType());
				break;
		}
	}
}
